<?php

namespace Module\Admin;

use Manager\Comment as Manager;
use W3\Html;
use W3\Exception;
use W3\Cookie;

!defined('W3_ROOT_DIR') AND exit;

/**
 * 评论编辑组件
 *
 * @author edikud
 * @date 2022/10/22
 * @copyright Copyright (c) 2022 W3 (http://www.mcooo.com)
 * @license GNU General Public License 2.0
 */
class Comment extends Manager
{
    /**
     * 初始化
     *
     * @access protected
     * @return void
     */
    protected function init()
    {
        # 必须为编辑员以上权限
        $this->auth->check('editor');
		
		# 定义变量默认数据
        $this->parameter([

			# 设置主体
			'main' => 'admin.comment',			
			
			# 分页大小
		    'pageSize'=>20,
			
			# 操作列表
		    'operate'=> [
			    'selectall'=>[
				    'name'=>__('全选'),
					'data-selectall'
				], 
				'delete'=>[
				    'name'=>__('删除'),
					'data-confirm'=>__('删除不可恢复，确定删除？'),
					'href'=>$this->request->makeUrl('do=delete')
				],
				
				'approved'=>[
				    'name'=>__('通过'),
					'href'=>$this->request->makeUrl('do=approved')
				],
				
				'waiting'=>[
				    'name'=>__('待审核'),
					'href'=>$this->request->makeUrl('do=waiting')
				],
				
				'spam'=>[
				    'name'=>__('标记垃圾'),
					'href'=>$this->request->makeUrl('do=spam')
				],
				
			],
			
			# 操作列表
		    'tabs'=> [
				'approved'=>[
				    'name' => __('已通过'),
					'href' => $this->request->makeUrl('status=approved&page=1'),
					'current'=> function($widget){
						return !isset($widget->request->status) || 'approved' == $widget->request->get('status');
					},
				],
				
				'waiting'=>[
				    'name' => __('待审核'),
					'href' => $this->request->makeUrl('status=waiting&page=1'),
					'current'=> function($widget){
						return 'waiting' == $widget->request->get('status');
					},
					'balloon'=> function($widget){
						
		                $stat = $this->widget('W3\Stat');
		
		                # 具有编辑以上权限,可以查看所有文章,反之只能查看自己的文章
		                $isAll = $this->auth->check('editor', true) && 'off' != $this->request->all;
						
						return $isAll ? (!isset($this->request->uid) ? $stat->waitingCommentsNum : $stat->currentWaitingCommentsNum) : $stat->myWaitingCommentsNum;
					}
				],
				
				'spam'=>[
				    'name' => __('垃圾'),
					'href' => $this->request->makeUrl('status=spam&page=1'),
					'current'=> function($widget){
						return 'spam' == $widget->request->get('status');
					},
					'balloon'=> function($widget){
						
		                $stat = $this->widget('W3\Stat');
		
		                # 具有编辑以上权限,可以查看所有文章,反之只能查看自己的文章
		                $isAll = $this->auth->check('editor', true) && 'off' != $this->request->all;
						
						return $isAll ? (!isset($this->request->uid) ? $stat->spamCommentsNum : $stat->currentSpamCommentsNum) : $stat->mySpamCommentsNum;
					}
				],
				
		        'all' => [
				    'name' => __('所有'),
					'href' => $this->request->makeUrl('all=on&page=1'),
					'current'=> function($widget){
						return !isset($widget->request->all) || 'on' == $widget->request->get('all');
					},
					'hide' => isset($this->request->uid)
				],
				
			    'me' => [
				    'name' => __('我的'),
				    'href' => $this->request->makeUrl('all=off&page=1'),
				    'current'=> function($widget){
					    return 'off' == $widget->request->get('all');
				    },
					'hide' => isset($this->request->uid)
			    ]
				
			],
			
		    'buttons'=> [
			
			    'approved'=>[
				    'name'=>__('通过'),
					'query'=> 'do=approved',
					'class'=>'w3-approved',
				],
			
			    'waiting'=>[
				    'name'=>__('待审核'),
					'query'=> 'do=waiting',
					'class'=>'w3-waiting'
				],
			
			    'spam'=>[
				    'name'=>__('垃圾'),
					'query'=> 'do=spam',
					'class'=>'w3-spam',
				],

			    'edit'=>[
				    'name'=>__('编辑'),
					'query'=> 'do=edit',
					'class'=>'w3-edit',
				],
			    'reply'=>[
				    'name'=>__('回复'),
					'query'=> 'do=reply',
					'class'=>'w3-reply',
				],	
			    'delete'=>[
				    'name'=>__('删除'),
					'query'=> 'do=delete',
					'class'=>'w3-delete',
					'data-confirm'=> __('确认删除此评论？'),
				]
			],
			
		], true);
		
	}

    /**
     * 绑定动作
     *
     * @access public
     * @return void
     */
    public function action()
    {
		$this->on(!$this->request->action || $this->request->is('action=index'))->index();
        $this->on($this->request->is('do=waiting'))->waitingComment();
        $this->on($this->request->is('do=spam'))->spamComment();
        $this->on($this->request->is('do=approved'))->approvedComment();
		$this->on($this->request->is('do=reply'))->reply();
		$this->on($this->request->is('do=edit'))->edit();
		$this->on($this->request->is('do=delete'))->delete();
    }

    /**
     * 标记为待审核
     */
    public function waitingComment()
    {
        $comments = $this->request->filter('int')->getArray('coid');
        $updateCount = 0;

        foreach ($comments as $comment) {
            if ($this->mark($comment, 'waiting')) {
                $updateCount++;
            }
        }

        /** 设置提示信息 */
        $this->notice(
		    $updateCount > 0 
			? __('评论已经被标记为待审核') 
			: __('没有评论被标记为待审核'), $updateCount > 0 ? 'success' : 'notice'
		);
		
		$this->goBack();
    }

    /**
     * 标记评论状态
     *
     * @param integer $coid 评论主键
     * @param string $status 状态
     * @return boolean
     * @throws Exception
     */
    private function mark($coid, $status)
    {
		$this->db
		    ->select()
		    ->from('table.comments')
		    ->where('coid = ?', $coid)
			->limit(1)
		    ->fetch([$this, 'push']);

        if ($this->allow('edit')) {

            /** 不必更新的情况 */
            if ($status == $this->status) {
                return false;
            }
			
			/** 更新评论 */
		    $updateRows = $this->updateComment($coid, ['status' => $status]);

            return $updateRows;
        }

        return false;
    }

    /**
     * 标记为垃圾
     *
     * @throws Exception
     */
    public function spamComment()
    {
        $comments = $this->request->filter('int')->getArray('coid');
        $updateCount = 0;

        foreach ($comments as $comment) {
            if ($this->mark($comment, 'spam')) {
                $updateCount++;
            }
        }

        /** 设置提示信息 */
        $this->notice(
		    $updateCount > 0 
			? __('评论已经被标记为垃圾') 
			: __('没有评论被标记为垃圾'), $updateCount > 0 ? 'success' : 'notice'
		);
		
		$this->goBack();
    }

    /**
     * 标记为展现
     *
     * @throws Exception
     */
    public function approvedComment()
    {
        $comments = $this->request->filter('int')->getArray('coid');
        $updateCount = 0;

        foreach ($comments as $comment) {
            if ($this->mark($comment, 'approved')) {
                $updateCount++;
            }
        }

        /** 设置提示信息 */
        $this->notice(
		    $updateCount > 0 
			? __('评论已经被通过') 
			: __('没有评论被通过'), $updateCount > 0 ? 'success' : 'notice'
		);
		
		$this->goBack();
    }

    public function index()
    {
        /** 按tag查询 */
        $select = $this->db
		    ->select()
		    ->from('table.comments');

        /** 过滤标题 */
        if (NULL != ($keywords = $this->request->filter('search')->keywords)) {
            $select->where('table.comments.text LIKE ?', '%' . $keywords . '%');
        }

        /** 如果具有编辑以上权限,可以查看所有文章,反之只能查看自己的文章 */
        if (!$this->auth->check('editor', true)) {
            $select->where('table.comments.uid = ?', $this->auth->uid);
        } else {
			
			if (isset($this->request->uid)) {
                $select->where('table.comments.uid = ?', $this->request->filter('int')->uid);
			} else if('off' == $this->request->all){
                $select->where('table.comments.uid = ?', $this->auth->uid);
			}
		}	

        if (in_array($this->request->status, ['approved', 'waiting', 'spam'])) {
            $select->where('table.comments.status = ?', $this->request->status);
        } elseif ('hold' == $this->request->status) {
            $select->where('table.comments.status <> ?', 'approved');
        } else {
            $select->where('table.comments.status = ?', 'approved');
        }

        //增加按文章归档功能
        if (isset($this->request->cid)) {
            $select->where('table.comments.cid = ?', $this->request->filter('int')->cid);
        }

		/** 计算数目 */
		$total = $select->count();
		$page = $this->request->get('page', 1);
		$pageUrl = $this->request->makeUrl('page=%page%');

        /** 提交查询 */
        $select
		    ->order('table.comments.coid', 'DESC')
            ->page($page, $this->parameter->pageSize)
			->get([$this, 'push']);

		$this->parameter([
			
			# 当前页数
			'page'         => $page,
			
			# 内容总数 
			'total'        => $total,
			
			# 页面Url 
			'pageUrl'      => $pageUrl
			
		]);
			
		# 版面布局
		$this->layout->set($this->tabs(false), 'top');
		$this->layout->set($this->indexList(), 'body');
		$this->layout->set($this->pagination(false), 'bottom');
		$this->view();

    }
	
    public function indexList()
    {
		$form = Html::form()
		    ->method('get')
			->addClass('mb-3');

		if(isset($this->request->all)){
			$form->set(Html::hidden('all', $this->request->filter('strip_tags')->all));
		}
		
		if(isset($this->request->type)){
			$form->set(Html::hidden('type', $this->request->filter('strip_tags')->type));
		}
		
		if(isset($this->request->status)){
			$form->set(Html::hidden('status', $this->request->filter('strip_tags')->status));
		}

		$keywords = Html::search('keywords', htmlspecialchars($this->request->keywords))->placeholder(__('请输入关键字'));
		
        if (!empty($_GET)){
			$keywords
			    ->reset
			    ->show()
				->title(__('取消筛选'))
				->href($this->adminUrl('comment', false));
	    }
		
		$form->set($keywords);

        if(isset($this->request->uid)){
			$uid = Html::hidden('uid', $this->request->filter('int')->uid);
			$form->set($uid);
        }

		$html = $form->render();

        if ($this->have()) {
			
			$table = Html::table();
			$table->addClass('w3-comments');
			$table->thead->preppend($this->operate(false));
			$table->thead->preppend('
                <colgroup>
					<col width="3%" />
                    <col width="12%" />
					<col width="82%" />
                </colgroup>
			');
			$table->head([
			    '',
			    __('作者'),
				__('内容'),
			]);
			
			$table->tbody->addClass('w3-commentList')->attribute('id', 'w3-comments');

			while ($this->next()){
				
				$button = '';
                foreach ($this->parameter->buttons as $v) 
		        {
					$query = $v['query'] ? $v['query'] . '&coid=' . $this->coid : 'coid=' . $this->coid ;
					$href = $this->request->makeUrl($query);
			        $name = $v['name'] ?? '';
			        unset($v['name']);
					unset($v['query']);
					$v['data-coid'] = $this->coid; //->addClass('btn btn-primary-soft')
		            $button .= Html::a($href, $name)->attributes($v)->render();
                }

			    $table->body([
				    Html::checkbox('coid', [$this->coid => '']),
					
				    '<div class="w3-commentInfo">
					    <img src="'. $this->author->avatar .'" width="40" height="40"/><br/>
						<a href="'. $this->request->makeUrl('uid=' . $this->uid) .'">'.$this->author->name .'</a>' 
						. ( $this->author->url ? '&nbsp;&nbsp;<a target="_blank" class="text-muted text-md" href="'.$this->author->domainPath.'"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link-2"><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line></svg></a>' : '' )
						. ($this->author->mail ? '<br/><span><a target="_blank" href="mailto:'.$this->author->mail.'">'.$this->author->mail.'</a></span>' : '')
						. ($this->author->ip ? '<span>'.$this->author->ip .'</span>' : '') . '</div>',

				    '<div class="w3-commentBody">
					    <div class="w3-comment-date">'. $this->dateWord .' 于 <a class="w3-comment-title" target="_blank" href="'. $this->request->makeUrl('coid=' . $this->coid) .'">'.$this->title .'</a>&nbsp;&nbsp;<a target="_blank" class="text-muted text-md" href="'.$this->permalink.'"><svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-link-2"><path d="M15 7h3a5 5 0 0 1 5 5 5 5 0 0 1-5 5h-3m-6 0H6a5 5 0 0 1-5-5 5 5 0 0 1 5-5h3"></path><line x1="8" y1="12" x2="16" y2="12"></line></svg></a>
					</div>
                    <div class="w3-comment-content">'. $this->content .'</div> 
                    <div class="w3-action hidden-by-mouse"> ' .$button. '</div>'

				]);
			}
			
			$html .= $table->wrap(Html::form()->removeClass('w3-form'))->render();
		}

		$url = $this->request->url(true);
		
		$cancel = __('取消');
		//$prefix = Cookie::prefix();
		$path = Cookie::path();
		
		
		$js = <<<EOF
$(document).ready(function () {

    // 记住滚动条
    function rememberScroll () {
        $(window).on('beforeunload', function () {
            $.cookie('__w3_comments_scroll', $('html').scrollTop(), {path : '$path'});
        });
    }

    // 自动滚动
    (function () {
        var scroll = $.cookie('__w3_comments_scroll');

        if (scroll) {
            $.cookie('__w3_comments_scroll', null, {path : '$path'});
            $('html, body').scrollTop(scroll);
        }
    })();

    $('.w3-delete').click(function () {
        var t = $(this), tip = t.data('confirm'), href = t.attr('href'), tr = t.parents('tr');

		if(tip) {
		    var num = t.data('num'), deletetext = t.html();
		    if(!num) {
			    t.data('num', 1);
			    t.html(tip);
			    setTimeout(function(){
				    t.data('num', 0);
				    t.html(deletetext);

			    }, 5000);
			    return false;
		    }
		}

        tr.fadeOut(function () {
            rememberScroll();
            window.location.href = href;
        });

        return false;
    });

    $('.w3-approved, .w3-waiting, .w3-spam').click(function () {
        rememberScroll();
        window.location.href = $(this).attr('href');
        return false;
    });


	var comments = $('#w3-comments');
	comments.on('click', '.w3-reply', function(e) {
        var t = $(this),
        replytext = t.html(),
	    url = t.attr('href'), 
		action = t.parent('.w3-action'),
		body = t.parents('.w3-commentBody'),
        form = $('<div class="w3-comment-form">'
			    +  '<p><textarea class="w3-comment-textarea" name="text" rows="6"></textarea></p>'
				+  '<p><a href="javascript:;" class="btn btn-primary btn-sm w3-comment-reply">'+replytext+'</a> <a href="javascript:;" class="btn btn-light btn-sm w3-comment-cancel">$cancel</a></p>'
				+  '</div>'),
		textarea = form.find('.w3-comment-textarea'),
		reply = form.find('.w3-comment-reply'),
		cancel = form.find('.w3-comment-cancel');
			
		form.insertBefore(action);
		action.hide();
		textarea.focus();
			
		cancel.click(function(e) {
			form.remove();
			action.show();
		});

		reply.click(function(e) {
				
			var text = textarea.val();
			if(text == '') {
				textarea.focus();
				return false;
			}
			reply.html('loading..');
			$.post(url, {text: text}, function(data) {
                if(data.success){
					action.before('<div class="w3-reply-text">'+data.comment.text+'</div>');
					form.remove();
				}
				action.show();
				reply.html(replytext);
		    });
		});
        return false;
    });
	
	comments.on('click', '.w3-edit', function(e) {
        var t = $(this), 
        edittext = t.html(),
		url = t.attr('href'),
		action = t.parent('.w3-action'),
		body = t.parents('.w3-commentBody'),
		content = body.find('.w3-comment-content'),
		form = $('<div class="w3-comment-form">'
		    +  '<p><textarea class="w3-comment-textarea" name="text" rows="6"></textarea></p>'
			+  '<p><a href="javascript:;" class="btn btn-primary btn-sm w3-comment-edit">'+edittext+'</a> <a href="javascript:;" class="btn btn-light btn-sm w3-comment-cancel">$cancel</a></p>'
			+  '</div>'),
		textarea = form.find('.w3-comment-textarea'),
		edit = form.find('.w3-comment-edit'),
		cancel = form.find('.w3-comment-cancel');

		form.insertBefore(content);
		textarea.val(content.html()).focus();
		action.hide();
		content.hide();
		cancel.click(function(e) {
			form.remove();
			content.show();
			action.show();
		});
			
		edit.click(function(e) {
			var text = textarea.val();
			if(text == '' || text == content.html()) {
				textarea.focus();
				return false;
			}
			edit.html('loading..');
			$.post(url, {text: text}, function(data) {
                if(data.success){
					content.html(data.comment.text);
					form.remove();
				}
			    edit.html(edittext);
				content.show();
				action.show();
		    });
	    });
        return false;
    });
});
EOF;

		add_script('comment', $js, ['jquery', 'common'], true);

		return $html;
	}

    /**
     * 回复评论
     *
     * @access public
     * @return void
     */
    public function reply()
    {
        $this->db
			->select()
		    ->from('table.comments')
			->where('table.comments.coid = ?', $this->request->filter('int')->coid)
			->limit(1)
			->fetch([$this, 'push']);
		
        if (!$this->allow('edit')) {
            $this->throwJson([
                'success' => 0,
                'message' => __('回复评论失败')
            ]);
        }

        $comments = [
            'cid'       =>  $this->cid,
            'created'   =>  $this->config->time,
            'ip'        =>  $this->request->ip(true),
            'ownerId'   =>  $this->ownerId,
            'uid'       =>  $this->auth->uid,
            'parent'    =>  $this->coid,
            'text'      =>  $this->request->text,
			'status'    =>  'approved'
        ];

		$commentId = $this->addComment($comments);
			
        $insertComment = $this->db
			->select()
		    ->from('table.comments')
			->where('table.comments.coid = ?', $commentId)
			->limit(1)
			->fetch([$this, 'push']);
			
        if ($commentId) {
            $this->throwJson([
                'success' => 1,
                'comment' => $insertComment
			]);
        } else {
            $this->throwJson([
                'success' => 0,
                'message' => __('回复评论失败')
            ]);

        }
    }

    public function edit()
    {
	    //sleep(3);
		
        $this->db
			->select()
		    ->from('table.comments')
			->where('table.comments.coid = ?', $this->request->filter('int')->coid)
			->limit(1)
			->fetch([$this, 'push']);
		
        if (!$this->allow('edit')) {
            $this->throwJson([
                'success' => 0,
                'message' => __('编辑评论失败')
            ]);
        }

        $comments = [
            'text' => $this->request->text
        ];

		$updateRows = $this->updateComment($this->coid, $comments);

        $updatedComment = $this->db
			->select()
		    ->from('table.comments')
			->where('table.comments.coid = ?', $this->coid)
			->limit(1)
			->fetch([$this, 'push']);
			
        if ($updateRows) {
            $this->throwJson([
                'success' => 1,
                'comment' => $updatedComment
			]);
        } else {
            $this->throwJson([
                'success' => 0,
                'message' => __('编辑评论失败')
            ]);

        }
    }

    public function delete()
    {
        $coids = $this->request->filter('int')->getArray('coid');
        $deleteCount = 0;

        foreach ($coids as $coid) 
		{
		    if($this->deleteComment($coid)){ 
				$deleteCount++;
			}
        }
			
        /** 设置提示信息 */
        $this->notice(
		    $deleteCount > 0 
			? __('评论已经删除') 
			: __('没有评论被删除'), $deleteCount > 0 ? 'success' : 'notice'
		);
		
		$this->goBack();
	}

}
